package com.ctvit.cch.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctvit.cch.ai.pojo.dto.AutoCategoryDTO;
import com.ctvit.cch.ai.pojo.vo.AutoCategoryVO;
import com.ctvit.cch.ai.service.ILlmService;
import com.ctvit.cch.core.mapper.HotCategoryFavoriteMapper;
import com.ctvit.cch.core.mapper.HotCategoryMapper;
import com.ctvit.cch.core.mapper.HotRecordMapper;
import com.ctvit.cch.core.mapper.SocialPlatformMapper;
import com.ctvit.cch.core.pojo.domain.HotCategory;
import com.ctvit.cch.core.pojo.domain.HotCategoryFavorite;
import com.ctvit.cch.core.pojo.domain.HotRecord;
import com.ctvit.cch.core.pojo.domain.SocialPlatform;
import com.ctvit.cch.core.pojo.dto.hot.HotRecordAddDTO;
import com.ctvit.cch.core.pojo.dto.hot.HotRecordEditDTO;
import com.ctvit.cch.core.pojo.dto.hot.HotRecordListDTO;
import com.ctvit.cch.core.pojo.vo.hot.HotRecordGetVO;
import com.ctvit.cch.core.pojo.vo.hot.HotRecordListVO;
import com.ctvit.cch.core.service.IHotRecordService;
import com.ctvit.cch.core.utils.AggregateScoreCalculatorUtils;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 热榜数据Service业务层处理
 *
 * @author heyingcheng
 * @date 2025/07/27
 */
@Slf4j
@Service
public class HotRecordServiceImpl extends ServiceImpl<HotRecordMapper, HotRecord> implements IHotRecordService {

    private final SocialPlatformMapper socialPlatformMapper;

    private final HotCategoryMapper hotCategoryMapper;

    private final HotCategoryFavoriteMapper hotCategoryFavoriteMapper;

    private final ILlmService llmService;

    private final ThreadLocal<Map<String, SocialPlatform>> platformMap = new ThreadLocal<>() {
        @Override
        protected Map<String, SocialPlatform> initialValue() {
            return socialPlatformMapper.selectList(new LambdaQueryWrapper<SocialPlatform>()).stream()
                    .collect(Collectors.toMap(SocialPlatform::getPlatformId, Function.identity()));
        }
    };

    public HotRecordServiceImpl(SocialPlatformMapper socialPlatformMapper,
            HotCategoryMapper hotCategoryMapper,
            HotCategoryFavoriteMapper hotCategoryFavoriteMapper,
            ILlmService llmService) {
        this.socialPlatformMapper = socialPlatformMapper;
        this.hotCategoryMapper = hotCategoryMapper;
        this.hotCategoryFavoriteMapper = hotCategoryFavoriteMapper;
        this.llmService = llmService;
    }

    @Override
    public TableDataInfo list(HotRecordListDTO dto) {
        List<Long> categoryIds = dto.getCategoryIds();
        if (CollectionUtils.isEmpty(categoryIds)) {
            categoryIds = hotCategoryFavoriteMapper.selectList(new LambdaQueryWrapper<HotCategoryFavorite>()
                    .eq(HotCategoryFavorite::getUserId, SecurityUtils.getUserId()))
                    .stream()
                    .map(HotCategoryFavorite::getCategoryId)
                    .collect(Collectors.toList());
        }

        // 使用多表联查方法查询数据
        Page<HotRecordListVO> page = baseMapper.selectHotRecordList(
                new Page<>(dto.getPageNum(), dto.getPageSize()),
                dto,
                SecurityUtils.getUserId());

        TableDataInfo tableDataInfo = new TableDataInfo();
        tableDataInfo.setCode(HttpStatus.SUCCESS);
        tableDataInfo.setMsg("查询成功");
        tableDataInfo.setRows(page.getRecords());
        tableDataInfo.setTotal(page.getTotal());

        return tableDataInfo;
    }

    @Override
    public boolean add(HotRecordAddDTO dto) {
        HotRecord entity = new HotRecord();
        BeanUtils.copyProperties(Objects.requireNonNull(dto), entity);
        entity.setRecordId(IdWorker.getIdStr());
        return save(entity);
    }

    @Override
    public boolean edit(HotRecordEditDTO dto) {
        HotRecord entity = new HotRecord();
        BeanUtils.copyProperties(Objects.requireNonNull(dto), entity);
        return updateById(entity);
    }

    @Override
    public HotRecordGetVO get(String id) {
        HotRecordGetVO target = new HotRecordGetVO();
        BeanUtils.copyProperties(Objects.requireNonNull(getById(id)), target);
        return target;
    }

    @Override
    public List<HotRecord> listByStatus(String status) {
        LambdaQueryWrapper<HotRecord> qWrapper = new LambdaQueryWrapper<>();
        qWrapper.eq(HotRecord::getStatus, status);
        qWrapper.orderByDesc(HotRecord::getCreateTime);
        qWrapper.last("LIMIT 10");
        return list(qWrapper);
    }

    /**
     * 处理指定天数内的热点记录，支持自定义处理逻辑
     *
     * @param days            天数
     * @param recordProcessor 每条记录的处理逻辑
     * @return 更新的记录数量
     */
    private int processHotRecords(int days, Consumer<HotRecord> recordProcessor) {
        // 初始化页码和每页数量
        int pageNum = 1;
        int pageSize = 20;

        // 获取指定天数前的时间
        LocalDateTime daysAgo = LocalDateTime.now().minusDays(days);

        // 循环处理所有分页数据
        boolean hasNextPage;
        do {
            // 创建分页对象
            Page<HotRecord> page = new Page<>(pageNum, pageSize);

            // 查询当前页数据（状态正常、未删除、更新时间在指定天数内）
            Page<HotRecord> resultPage = page(page, new LambdaQueryWrapper<HotRecord>()
                    .eq(HotRecord::getStatus, "0")
                    .ge(HotRecord::getUpdateTime, daysAgo)
                    .orderByAsc(HotRecord::getUpdateTime));

            List<HotRecord> hotRecords = resultPage.getRecords();

            // 处理当前页数据
            if (CollectionUtils.isNotEmpty(hotRecords)) {
                hotRecords.forEach(recordProcessor);
            }

            // 检查是否还有下一页数据
            hasNextPage = resultPage.hasNext();

            // 如果有下一页，进入下一页
            if (hasNextPage) {
                pageNum++;
            }
        } while (hasNextPage);

        return pageNum - 1; // 返回处理的页数，实际更新数量由处理器内部维护
    }

    @Override
    public int aggregate(int days) {
        // 使用原子变量记录更新数量
        AtomicInteger updateCount = new AtomicInteger(0);

        // 调用公共方法处理热点记录，传入聚合评分的处理逻辑
        processHotRecords(days, hotRecord -> {
            try {
                SocialPlatform platform = Objects.requireNonNull(platformMap.get())
                        .get(hotRecord.getPlatformId());

                // 计算聚合评分
                BigDecimal newAggregateScore = BigDecimal
                        .valueOf(AggregateScoreCalculatorUtils.calculateAggregateScore(
                                platform.getPlatformWeight(),
                                platform.getMaxRawScore(),
                                hotRecord.getScore(),
                                hotRecord.getRank(),
                                hotRecord.getUpdateTime(),
                                hotRecord.getSpreadWide(),
                                hotRecord.getInfluenceDepth(),
                                hotRecord.getCreativeValue()));

                // 更新聚合分数（只有当分数变化时才更新）
                if (hotRecord.getAggregateScore() == null
                        || newAggregateScore.compareTo(hotRecord.getAggregateScore()) != 0) {
                    update(new LambdaUpdateWrapper<HotRecord>()
                            .eq(HotRecord::getRecordId, hotRecord.getRecordId())
                            .set(HotRecord::getAggregateScore, newAggregateScore));
                    updateCount.incrementAndGet();
                }
            } catch (Exception e) {
                // 记录错误但继续处理其他记录
                log.error("处理热点记录聚合分数异常, 记录ID:[{}]", hotRecord.getRecordId(), e);
            }
        });

        return updateCount.get();
    }

    @Override
    public int recategory(int days) {
        List<HotCategory> hotCategories = hotCategoryMapper.selectList(new LambdaQueryWrapper<HotCategory>()
                .eq(HotCategory::getShowFlag, NumberUtils.INTEGER_ONE.toString())
                .orderByAsc(HotCategory::getOrderNum));

        // 将分类列表转换为LinkedHashMap，保持业务顺序（按orderNum排序）
        Map<String, HotCategory> categoryMap = hotCategories.stream()
                .collect(Collectors.toMap(
                        HotCategory::getCategoryName,
                        Function.identity(),
                        (existing, replacement) -> existing,
                        LinkedHashMap::new));

        // 使用原子变量记录更新数量
        AtomicInteger updateCount = new AtomicInteger(0);

        // 调用公共方法处理热点记录，传入重新分类的处理逻辑
        processHotRecords(days, hotRecord -> {
            try {
                AutoCategoryVO categoryVo = llmService
                        .categorize(new AutoCategoryDTO(hotRecord.getTitle(), hotRecord.getKeyword(),
                                StringUtils.joinWith(",", categoryMap.keySet().toArray(new String[0]))));

                // 示例：根据热点标题和关键字进行分类
                Long newCategoryId = categoryMap.getOrDefault(categoryVo.getCategoryName(), new HotCategory())
                        .getCategoryId();
                Assert.notNull(newCategoryId, "分类ID不能为空");

                // 只有当分类ID变化时才更新
                if (newCategoryId != null && !Objects.equals(hotRecord.getCategoryId(), newCategoryId)) {
                    update(new LambdaUpdateWrapper<HotRecord>()
                            .eq(HotRecord::getRecordId, hotRecord.getRecordId())
                            .set(HotRecord::getCategoryId, newCategoryId));
                    updateCount.incrementAndGet();
                }
            } catch (Exception e) {
                // 记录错误但继续处理其他记录
                log.error("处理热点记录重新分类异常, 记录ID:[{}]", hotRecord.getRecordId(), e);
            }
        });

        return updateCount.get();
    }

}
